import React, {Component, Fragment} from 'react';
import PropTypes from 'prop-types';
import {getStyles} from '@/utils/utils';
// 克隆子元素button 并添加事件方法 HOC：higher order component
const withClick = (element, handleClick = () => {}) => {
    return <element.type {...element.props} onClick={handleClick}></element.type>;
};

export default class FullScreen extends Component {
    constructor(props) {
        super(props);
        this.timerid = null; // timerid

        this.state = {
            isFullScreen: props.defaultFullScreen || false
        };
    }
    // 全屏显示
    fullScreen = () => {
        const isFullScreen = this.state.isFullScreen;
        if (!this.state.isFullScreen) {
            this.requestFullScreen();
        } else {
            this.exitFullscreen();
        }
        this.setState({isFullScreen: !isFullScreen}, this.handleChange);
    };
    // 进入全屏
    requestFullScreen = () => {
        const container = document.querySelector(this.props.fullScreenSelector);
        if (container.requestFullscreen) {
            container.requestFullscreen();
        } else if (container.mozRequestFullScreen) {
            container.mozRequestFullScreen();
        } else if (container.webkitRequestFullScreen) {
            container.webkitRequestFullScreen();
        }
    };
    // 退出全屏
    exitFullscreen = () => {
        const dom = document;
        if (dom.exitFullscreen) {
            dom.exitFullscreen();
        } else if (dom.mozCancelFullScreen) {
            dom.mozCancelFullScreen();
        } else if (dom.webkitCancelFullScreen) {
            dom.webkitCancelFullScreen();
        }
    };
    // 监听作用
    watchFullScreen = () => {
        window.addEventListener('resize', this.handleResize, false);
    };
    // 移除监听
    removeWatchFullScreen = () => {
        window.removeEventListener('resize', this.handleResize, false);
    };
    // 给父组件传递数据
    handleChange = () => {
        this.props.change(this.state.isFullScreen || false);
    };
    // 浏览器窗口大小变化、全屏关闭全屏会触发
    handleResize = () => {
        clearTimeout(this.timerid);
        this.timerid = setTimeout(() => {
            if (this.props.isListenResize) {
                this.handleCalcContainerStyle();
            }

            if (this.state.isFullScreen !== this.checkFull()) {
                this.setState({isFullScreen: this.checkFull()}, this.handleChange);
            }
        }, 300);
    };
    // 判断是否为全屏
    checkFull = () => {
        let isFull = window.fullScreen || document.webkitIsFullScreen || document.msFullscreenEnabled;
        // document.fullscreenEnabled 判断浏览器是否支持全屏
        // https://developer.mozilla.org/zh-CN/docs/Web/API/Document/mozFullScreenEnabled
        // window.fullScreen 判断浏览器是否在全屏模式下，仅在Gecko 1.9（Firefox 3）以及之后的版本中有意义，详情参见后附备注。
        // https://developer.mozilla.org/zh-CN/docs/Web/API/Window/fullScreen

        return document.fullscreenEnabled ? isFull : false;
    };
    // 计算容器样式
    handleCalcContainerStyle = () => {
        const {fullScreenSelector, listenResize} = this.props;
        const container = document.querySelector(fullScreenSelector);
        if (!container) {
            throw new Error(`${fullScreenSelector} 不存在`);
        }
        if (typeof listenResize !== 'function') {
            throw new Error('listenResize 不是函数');
        } else {
            const {width, height} = getStyles(container);
            const styles = {width: width.replace('px', '') - 0, height: height.replace('px', '') - 0};
            listenResize(styles);
        }
    };
    // react生命周期挂载之后
    componentDidMount() {
        this.watchFullScreen();
    }
    // react生命周期卸载之前
    componentWillUnmount() {
        this.removeWatchFullScreen();
    }

    render() {
        return <Fragment>{withClick(this.props.children, this.fullScreen)}</Fragment>;
    }
}

FullScreen.propTypes = {
    defaultFullScreen: PropTypes.bool,
    change: PropTypes.func, // 初始化会触发一次，全屏或者关闭全屏时触发
    fullScreenSelector: PropTypes.string.isRequired,
    isListenResize: PropTypes.bool, // true: 监听浏览器resize事件回调，计算当前窗口大小，第二个参数是当前全屏容器  false: 默认值
    listenResize: PropTypes.func // isListenResize === true时 有效
};
FullScreen.defaultProps = {
    defaultFullScreen: false,
    isListenResize: false,
    listenResize() {}
};
